<template>
  <el-form label-width="100px" v-bind="attr" ref="formRef" :model="lowCodeComponentData">
    <div :style="{ display: 'grid', 'grid-template-columns': `repeat(${columnCount}, 1fr)` }">
      <template v-if="isPrimitive(schema.body)">{{ schema.body }}</template>
      <template v-else-if="isPlainObj(schema.body)">
        <LowCode
          v-if="schema.body.prop"
          :schema="schema.body"
          v-model="lowCodeComponentData[schema.body.prop]"
        />
        <LowCode v-else :schema="schema.body" />
      </template>
      <template v-if="Array.isArray(schema.body)">
        <template v-for="(item, index) in schema.body">
          <LowCode
            v-if="item.prop"
            v-model="lowCodeComponentData[item.prop]"
            :schema="item"
            style="width: 100%"
            :key="item.key || item.prop"
          />
          <LowCode :schema="item" style="width: 100%" :key="item.key || index" v-else />
        </template>
      </template>
    </div>
  </el-form>
</template>

<script setup>
import { isPrimitive, isPlainObj, deepCopy } from '@/utils/index'
import { ref, onMounted, provide, inject, getCurrentInstance, watchEffect } from 'vue'
import LowCode from '@/components/LowCode.vue'
import { filterAttrByExclude, handleObject } from '../../common/util'
import { handleApi } from '../../common/api'

const instance = getCurrentInstance()

const props = defineProps({
  schema: {
    type: Object,
    required: true
  }
})
const lowCodeComponentData = ref({})

const formRef = ref()
const attr = ref()
const columnCount = ref(props.schema.columnCount || 1)

const formProps = {
  formRef,
  model: lowCodeComponentData.value,
  schema: props.schema,
  resetFields,
  getFieldsValue,
  updateDefaultValue
}

provide('lowCodeForm', formProps)

const lowCodeCrud = inject('lowCodeCrud')

const lowCodeDialog = inject('lowCodeDialog')

const lowCodeDrawer = inject('lowCodeDrawer')

onMounted(() => {
  console.log('lowCodeDialog', lowCodeDialog);
  if (lowCodeCrud) {
    lowCodeCrud.setForm(formProps)
  }
  if (lowCodeDialog) {
    lowCodeDialog.setForm(formProps)
  }
  if (lowCodeDrawer) {
    lowCodeDrawer.setForm(formProps)
  }
})

const formAttrs = ['data', 'columnCount']
watchEffect(() => {
  const schema = props.schema
  const data = schema.data

  attr.value = filterAttrByExclude(formAttrs, schema)
  const body = schema.body
  columnCount.value = schema.columnCount || 1 // 每行展示几列

  if (data && isPlainObj(data)) {
    const initData = handleObject(deepCopy(data), instance)
    for (const key in initData) {
      lowCodeComponentData.value[key] = initData[key]
    }
  }

  if (Array.isArray(body)) {
    body.forEach((item) => {
      if (item.prop) {
        lowCodeComponentData.value[item.prop] = item.defaultValue || undefined
      } else {
        console.warn('form-item组件未设置props属性')
      }
    })
  }
})

function getInitApi() {
  const initApi = props.schema.initApi

  if (!initApi) {
    return
  }
  handleApi(initApi, instance).then((data) => {
    for (const key in lowCodeComponentData.value) {
      lowCodeComponentData.value[key] = Reflect.get(data, key)
    }
  })
}

function resetFields(fields = []) {
  if (fields && fields.length) {
    fields.forEach((key) => {
      lowCodeComponentData.value[key] = getDefaultValue(key)
    })
  } else {
    for (const key in lowCodeComponentData.value) {
      lowCodeComponentData.value[key] = getDefaultValue(key)
    }
  }
}

function getFieldsValue(fields = []) {
  const obj = {}
  if (fields && fields.length) {
    fields.forEach((key) => {
      obj[key] = lowCodeComponentData.value[key]
    })
  } else {
    for (const key in lowCodeComponentData.value) {
      obj[key] = lowCodeComponentData.value[key]
    }
  }
  return obj
}

function updateDefaultValue(fieldValues = {}) {
  for (const key in fieldValues) {
    const defaultValue = fieldValues[key]
    const body = props.schema.body
    if (isPlainObj(body)) {
      if (body.prop && key === body.prop) {
        body.defaultValue = defaultValue
        lowCodeComponentData.value[key] = defaultValue
      }
      return
    } else if (Array.isArray(body)) {
      const item = body.find((b) => b.prop === key)
      if (item) {
        item.defaultValue = defaultValue
        lowCodeComponentData.value[key] = defaultValue
      }
    }
  }
}

function getDefaultValue(prop) {
  const body = props.schema.body
  if (isPlainObj(body)) {
    if (body.prop && prop === body.prop) {
      return body.defaultValue
    }
  } else if (Array.isArray(body)) {
    for (const item of body) {
      if (item.prop === prop) {
        return item.defaultValue
      }
    }
  }
}

getInitApi()
</script>
